package com.momo.hystrix.controller;

import com.momo.hystrix.service.UserService;
import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCollapserProperties;
import com.netflix.hystrix.HystrixCommand;
import pojo.User;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * HystrixCollapser<List<User>,User,Integer>
 * 三个范型的类型1、返回结果类型 2、响应的类型 3、入参数的类型
 */
public class UserCollapseCommand extends HystrixCollapser<List<User>, User, Integer> {

    private UserService userService;

    private Integer id;

    public UserCollapseCommand(UserService userService, Integer id) {
        /**
         * 设置合并请求的时间间隔，比如说我们设定一个请求合并的为200mm 算一次合并的请求
         */
        super(HystrixCollapser.Setter.withCollapserKey(HystrixCollapserKey
                .Factory
                .asKey("UserCollapseCommand"))
                .andCollapserPropertiesDefaults(HystrixCollapserProperties
                        .Setter()
                        .withTimerDelayInMilliseconds(200)));//间隔200毫秒以内算一次批处理起请求
        this.userService = userService;
        this.id = id;
    }

    /**
     * 请求参数
     *
     * @return
     */
    @Override
    public Integer getRequestArgument() {
        return id;
    }

    /**
     * 请求合并的方法
     *
     * @param collection 所有的请求的的一个集合，包含了我们合并一个请求内的所有的参数。
     * @return 返回一个指定好的HystrixCommand
     */
    @Override
    protected HystrixCommand<List<User>> createCommand(Collection<CollapsedRequest<User, Integer>> collection) {
        ArrayList<Integer> integers = new ArrayList<>(collection.size());
        /**
         * 把需要传递的参数进行拼装和组合，传递给UserBatchCommand
         * 使得provider获得参数后继续处理
         */
        for (CollapsedRequest<User, Integer> uicq : collection) {
            integers.add(uicq.getArgument());
        }
        /**
         * 这里是链接和核心部分，这里使用了我们设定的UserBatchCommand
         */
        return new UserBatchCommand(integers, userService);
    }

    /**
     * 请求后的结果
     *
     * @param users      provider返回的请求之后结果
     * @param collection 合并之后的请求
     */
    @Override
    protected void mapResponseToRequests(List<User> users, Collection<CollapsedRequest<User, Integer>> collection) {
        int count = 0;
        for (CollapsedRequest<User, Integer> userIntegerCollapsedRequest : collection) {
            /*
                因为请求的过程也是一次请求的
                给合并的请求分配结果，也就是我们设置的请求的响应值
                给没一个请求设置响应的结果，这里设置
             */
            userIntegerCollapsedRequest.setResponse(users.get(count++));
        }
    }
}
